package playGround.square;

import java.math.BigDecimal;
import java.util.Map;

import playGround.border.Border;
import playGround.border.Wall;
import playGround.dungeon.Direction;
import be.kuleuven.cs.som.annotate.Immutable;
import be.kuleuven.cs.som.annotate.Raw;
/**
 * Class representing a rock: a square surrounded by walls whose temperature is the average of the 
 * squares surrounding this square and whose humidity is 0.
 * @invar	The humidity of each rock must be equal to 0 degrees.
 * 			|this.canHaveHumidity(super.getHumidity);
 * @invar	The temperature of each rock is the average of the temperature of the surrounding squares(non-rock).
 * 			|isValidTemperature(super.getTemperature())
 * @invar	Each rock must have valid borders.
 * 			|areValidBorders()
 * @author 	Maarten en Niels
 * @version 2.3
 *
 */
public class Rock extends Square {
	/**
	 * Constructor of the Rock class
	 * @param 	temperatureScale 
	 * 			The temperaturescale for this new Rock.
	 * @post    The temperatureScale of the rock is set to the indicated temperatureScale.
	 * 			|new.getTemperatureScale() == temperatureScale	
	 * @post	The humidity is set to 0.
	 * 			|new.getHumidity().equals(new BigDecimal(0))
	 * @post	Temperature is set to 0.
	 * 			|new.getTemperature==0
	 * @post	The borders of this are filled with walls.
	 * 			|for each direction of new.getDirections()
	 * 			|new.getBorder(direction) instanceof Wall
	 */
	@Raw
	public Rock(Scale temperatureScale){
		super(0, new BigDecimal(0), temperatureScale);
		super.addBorder(Direction.NORTH, new Wall(false));
		super.addBorder(Direction.EAST, new Wall(false));
		super.addBorder(Direction.SOUTH, new Wall(false));
		super.addBorder(Direction.WEST, new Wall(false));
		super.addBorder(Direction.CEILING, new Wall(false));
		super.addBorder(Direction.FLOOR, new Wall(false));
	}
	/**
	 * Default constructor for Rock.
	 * @effect	This rock is initialized with temperature 0, humidity 0, temperatureScale Celcius and surrounded by walls.
	 * 			|this(Scale.CELSIUS)
	 */
	@Raw
	public Rock(){
		this(Scale.CELCIUS);
	}
	/**
	 * @effect	The temperature of this rock is set to the temperature calculated in calculateTemperature.
	 * 			|super.setTemperature(this.calculateTemperature())
	 */
	public void changeTemperature(){
		super.setTemperature(calculateTemperature());
	}
	/**
	 * Method to calculate the temperature of this rock.
	 * @return 	The result is the average temperature of the surrounding (non-rock) squares.
	 * 		 	|for each border in getAllBorders().values()
	 * 			| square = border.getSquareAt(0)
	 *  	 	| if(square!=null && square != this && !(square.temperatureIsDependentUponNeighbours()))
	 *  		| nbSquares++
	 *		 	| sum+=square.getTemperature()
	 *			| if(nbSquares != 0)
	 *		 	| then result==(sum/nbSquares)
	 *@return	The result is 0 if there aren't any squares surrounding this rock.
	 *			| if(nbSquares ==0)
	 *			| then result==0
	 */
	public int calculateTemperature(){
		int nbSquares=0;
		int sum=0;
		for(Border border:super.getAllBorders().values()){
			Square square=border.getSquareAt(0);
			if(border.getNbSquares()==2){
				if(square==this)
					square=border.getSquareAt(1);
				if(square!=null && !(square.temperatureIsDependentUponNeighbours())){
					nbSquares++;
					sum+=square.getTemperature();
				}
			}
		}
		if(nbSquares==0){
			return 0;
		}
		else{
			return(sum/nbSquares);
		}
	}
	/**
	 * @param 	temperature the temperature to check
	 * @return	True if the temperature is equal to the temperature calculated in calculateTemperature and if it is valid.
	 * 			|result==(super.isValidTemperature(temperature)&&(temperature==calculateTemperature()))
	 */
	@Override
	public boolean isValidTemperature(int temperature){
		if( !super.isValidTemperature(temperature))
			return false;
		if(super.getInitialized())	
			return (temperature==calculateTemperature());
		return true;
	}
	
	/**
	 * Method to check if the given humidity is a valid one.
	 * @param humidity 	the humidity to check
	 * @return	True if the given humidity has value 0.
	 * 			|result== (humidity.equals(new BigDecimal(0)))
	 */
	@Override
	public boolean canHaveHumidity(BigDecimal humidity){
		return humidity.equals(new BigDecimal(0));
	}

	/**
	 * returns whether the rock can have this borders
	 * @return a rock may only contain walls
	 * 			| result == onlyContainsWalls(borders) && super.canHaveBorders(borders)
	 */
	@Override
	public boolean canHaveBorders(Map<Direction, Border> borders) {
		return (super.canHaveBorders(borders)&&onlyContainsWalls(borders));
	}
	/**
	 * this method checks whether the square contains only walls
	 * @param borders the map with the direction and the border for that direction
	 * @return true if the square has only walls as border
	 * 		| for each border in borders.values()
	 * 		| if(border == null || !(Wall.class.isInstance(border)))
	 * 		| then result== false
	 */
	public boolean onlyContainsWalls(Map<Direction, Border> borders) {
		boolean check=true;
		for(Border border:borders.values()){
			if(border==null)
			check=false;
			if(!(Wall.class.isInstance(border)))
			check=false;
		}
		return check;
	}
	/**
	 * This method returns whether or not this square has valid borders
	 * @return if the super condition is true and it only has walls as border.
	 * 		| result == onlyContainsWalls(super.getAllBorders()) && super.areValidBorders()
	 */
	@Override
	public boolean areValidBorders(){
		return (super.areValidBorders()&&onlyContainsWalls(super.getAllBorders()));
	}
	/**
	 * This method checks whether this border can be removed
	 * @return false
	 * 		| super.setBorderCanBeRemoved(false)
	 */
	@Override
	protected void setBorderCanBeRemoved(){
		super.setBorderCanBeRemoved(false);
	}
	/**
	 * Method to check if one can go from this rock to the given square.
	 * @param square the square you want to know of whether you can go there.
	 * @return  false, because you can't go from a rock to another square.
	 * 			|result==false
	 */
	@Override @Immutable
	public boolean canNavigateTo(Square square) {
		return false;
	}
	/**
	 * This method identifies as rock, the temperature is dependent on the neighbours
	 * @return true
	 * 		| result == true
	 */
	@Override @Immutable
	public boolean temperatureIsDependentUponNeighbours() {
		return true;
	}

	

}
